package com.mongo.jdbc.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bson.Document;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mongodb.client.MongoDatabase;

/**
 * 
 * @author:binggong
 * @createtime:2019年11月8日 下午3:56:35
 * @version:V.0.1
 * @tag: mongodb 传递命令得到返回结果的工具类
 *
 */
public class JdbcMongodbCommand{

//	MongoDatabase db = null;
	
	//设置最大返回条数
	private static final int reulstMaxsize = 10000;
	
	private Gson gson = GsonTools.getGson();
	
	public JdbcMongodbCommand() {
		
	}

	
//	public ApiCloudsMongodbCommand (MongoDatabase db) {
//		this.db = db ;
//	}  
	
	/**
	 * 执行命名，得到返回结果
	 * @param script 命令脚本
	 * @return
	 */
	public Object command (MongoDatabase db,String script) throws Exception{
		String jsonScript = script;
		Document paramter = null;
		Object resultString = null;
		if(script == null || script.trim().equals("")) {
			return null;
		} else {
			jsonScript = jsonScript.trim();
			if (jsonScript.startsWith("db") || jsonScript.startsWith("DB")) {
				jsonScript = parseScriptString(jsonScript);
			}

			Document result = null;
			if (jsonScript.indexOf(";")!=-1) {
				//可能有多个脚本需要执行
				List<String> moreScriptList = ExtractMessage.getMoreScript(jsonScript);
				boolean showResult = false; // 1.如果有查询内容就显示查询的内容，如果没有就显示执行结果内容
				for (String paramterStr : moreScriptList ) {
					paramter = Document.parse(paramterStr);
					result = db.runCommand(paramter);
					if (result.containsKey("cursor")) {

						Document d = (Document) result.get("cursor");
						List firstBatch = (List) d.get("firstBatch");
						resultString = firstBatch ; //gson.toJson(firstBatch);
						showResult = true;
					} else {
						if (!showResult) {
							resultString = result.toJson();
						}
						
					}
				}
				
				
			}else {
				paramter = Document.parse(jsonScript);
				result = db.runCommand(paramter);
				if (result.containsKey("cursor")) {

					Document d = (Document) result.get("cursor");
					List firstBatch = (List) d.get("firstBatch");
					resultString = gson.toJson(firstBatch);

				} else {
					resultString = result.toJson();
				}
			}
		

		
		}
		
		return resultString;
	}
	
	
	/**
	 * 把解析的mongodb命令转换成
	 * @param script
	 * @return
	 */
	public String parseScriptString(String script) throws Exception {
		String result = null;
		if(script == null || script.trim().equals("")) {
			return null;
		} 
		script = script.trim();
		
		if ( script.startsWith("db") || script.startsWith("DB")) {
			
			//判断是否含有mybatis特有标签的脚本，如果是则mybatis脚本无法解析，直接返回
			if(ExtractMessage.isCheckMyBatisScript(script)) {
				//是mybatis脚本
				result = script;
				
			} else {
				
				//判断是否为多个脚本
				List<String> moreScriptList = ExtractMessage.getMoreScript(script);
				result = "";
				Document docResult = null;
				for (String sc  : moreScriptList ) {
					
					docResult = parseScript(sc);
					if (docResult.size() == 0) {
						throw new Exception("mongodb脚本解析有误，请重新输入!");
					}else {
						result += docResult.toJson()+" ; ";	
					}
					
				}
				
				result = result.substring(0,result.length()-2);
				
			}
			
			

			
		}else {
			result = script;
		}
		
		String regex = "\"\\#\\{([^}]*)\\}";
		Pattern compile = Pattern.compile(regex);
		Matcher matcher = compile.matcher(result);
		StringBuffer bf = new StringBuffer(result);
		int j=0;
		
		while(matcher.find()){
			
			String group = matcher.group()+"\"";
			int index = result.indexOf(group);

			 bf = bf.delete(index-j, index-j+1);
		     bf = bf.delete((index+group.length()-2-j), (index+group.length()-1-j));
		     j++;
		     j++;
		}
		
		
		String regex1 = "\"'\\#\\{([^}]*)\\}";
		Pattern compile1 = Pattern.compile(regex1);
		Matcher matcher1 = compile1.matcher(bf.toString());
		int x=0;
		result = bf.toString();
		while(matcher1.find()){
			
			String group = matcher1.group()+"'\"";
			
			int index = result.indexOf(group);
			 bf = bf.delete(index-x, index-x+2);
		     bf = bf.delete((index+group.length()-4-x), (index+group.length()-2-x));
		     x++;
		     x++;
		}
		
		
		String regex2 = "\'\\#\\{([^}]*)\\}";
		Pattern compile2 = Pattern.compile(regex2);
		Matcher matcher2 = compile2.matcher(bf.toString());
		int x2=0;
		result = bf.toString();
		while(matcher2.find()){
			
			String group = matcher2.group()+"'";
			
			int index = result.indexOf(group);
			 bf = bf.delete(index-x2, index-x2+1);
		     bf = bf.delete((index+group.length()-2-x2), (index+group.length()-1-x2));
		     x2++;
		     x2++;
		}
		

		return bf.toString();
	}
	
	
	/**
	 * 解析mongodb命令类脚本，并生成Document对象
	 *  db.tb_goods.find({}).limit(5)
	 * @param script
	 * @return
	 */
	public Document parseScript(String script) {
		
		//获取表名
		int tableIndex = script.substring(3).indexOf(".")+3;
		String table = script.substring(3, tableIndex);
		
		int commandIndex = script.indexOf("(");


		String command = script.substring(tableIndex+1,commandIndex);
		Document document = new Document();
		
		
		String strs[] = script.substring(commandIndex+1).split("\\)\\.");
		
		String commandParamter = strs[0];
		
		if (commandParamter.endsWith(")")) {
			commandParamter = commandParamter.substring(0,commandParamter.length()-1);
		}
		
		if (command.equals("find")) {
			//find查询命令
			document.put("find", table);
			if (!commandParamter.equals("")) {
				if (commandParamter.startsWith("{")) {
					//json对象
					//如果
					commandParamter=commandParamter.trim();
					
					List<String> list = ExtractMessage.extractMessage(commandParamter);
					
					
					int endIndex = commandParamter.indexOf("}");
					
					if (list.size() > 1) {
						
						document.put("filter", Document.parse(list.get(0)));
						document.put("projection", Document.parse(list.get(1)));
						
					} else {
						document.put("filter", Document.parse(commandParamter));
					}
					
					

				} else {
					document.put("filter", commandParamter);
				}
			}
			
		} else if (command.equals("deleteMany") || command.equals("deleteOne")) {
			//删除命名
			document.put("delete", table);
			
			int limit =0;
			if (command.equals("deleteOne")) {
				limit = 1;
			}
			
			if (!commandParamter.equals("")) {
				List<Document> deletes = new ArrayList<Document>();
				Document deleteDoc = new Document();
				//Document deletes =new 
				if (commandParamter.startsWith("{")) {
					deleteDoc.put("q", Document.parse(commandParamter));
					//json对象

				} else {
					deleteDoc.put("q", commandParamter);
				}
				deleteDoc.put("limit", limit);
				deletes.add(deleteDoc);
				
				document.put("deletes", deletes);
			}

		} else if (command.equals("update") || command.equals("updateOne") || command.equals("updateMany")) {
			//修改命令
			document.put("update", table);
			
			List<Document> updates = new ArrayList<Document>();
			Document updateObj = new Document();
			if (commandParamter.startsWith("{")) {
				updates = gson.fromJson("["+commandParamter+"]", new TypeToken<List<Document>>() {}.getType());
			}
			
			List<Document> updatesNews = new ArrayList<Document>();
			List<Document> uList = new ArrayList<Document>();
			for(Document o : updates ) {
				if ( o.containsKey("$set") || o.containsKey("$unset") || o.containsKey("$replaceWith")) {
					uList.add(o);
					//updateObj.put("u", o);
				} else if (o.containsKey("upsert")){
					Object ovalue = o.get("upsert");
					if (o.size() == 1 ) {
						if (ovalue instanceof Boolean ) {
							updateObj.put("upsert", ovalue);
						}
					}
					
				}else if (o.containsKey("multi")){
					Object ovalue = o.get("multi");
					if (o.size() == 1 ) {
						if (ovalue instanceof Boolean ) {
							updateObj.put("multi", ovalue);
						}
					}
				}else{
					updateObj.put("q", o);
				}
			}
			
			if (uList.size() > 0 ) {
				updateObj.put("u", uList);
			}
			
			if (command.equals("updateMany") || command.equals("update") ) {
				updateObj.put("multi", true);
			}
			
			updatesNews.add(updateObj);
			document.put("updates", updatesNews);
			
			
		}else if (command.equals("insert")) {
			//添加
			document.put("insert", table);
			
			List<Document> inserts = new ArrayList<Document>();
			if (commandParamter.startsWith("{")) {
				inserts = new Gson().fromJson("["+commandParamter+"]", new TypeToken<List<Document>>() {}.getType());
			}
			document.put("documents", inserts);
			
			
		} else if (command.equals("distinct")) {
			//统计查询
			document.put("distinct", table);
			
			//获取key
			int index = commandParamter.indexOf(",");
			
			String filed = null;
			if (index == -1 ) {
				document.put("key", commandParamter.trim());
			} else {
				filed = commandParamter.substring(0, commandParamter.indexOf(","));
				document.put("key", filed);
				document.put("query", Document.parse(commandParamter.substring(commandParamter.indexOf(",")+1)));


			}
					
		} else if (command.equals("aggregate")) {
			//聚合查询
			document.put("aggregate", table);
			
			
			//获取转换成List<String>
			commandParamter = commandParamter.trim();
			List<Document> pipeline = new ArrayList<Document>();
			
			if (commandParamter.startsWith("[")) {
				pipeline = gson.fromJson(commandParamter, new TypeToken<List<Document>>() {}.getType());
				
			}else if (commandParamter.startsWith("{")) {
			
				List<String> list = ExtractMessage.extractMessage(commandParamter);
				
				for (String json : list ) {
					if (!json.trim().equals("")) {
						pipeline.add(Document.parse(json));	
					}
					
				}
			}
			
			document.put("pipeline", pipeline);
			
		}
		
		
		
		
		for(int i = 1 ;i< strs.length ;i++ ) {
			String commandFilter = strs[i];
			// 获取命令
			int getCmdIndex = commandFilter.indexOf("(");
			String getCmd = commandFilter.substring(0,getCmdIndex);
			String getCmdValue = commandFilter.substring(getCmdIndex+1,commandFilter.length());
			
			if (getCmdValue.endsWith(")")) {
				getCmdValue = getCmdValue.substring(0,getCmdValue.length()-1);
			}
			
			if (getCmdValue.startsWith("{")) {
				document.put(getCmd, Document.parse(getCmdValue));
				
			}else if (isDoubleOrFloat(getCmdValue)) {
				document.put(getCmd, Double.parseDouble(getCmdValue));
			}else if (getCmdValue.startsWith("#{")&&getCmdValue.indexOf("}")!=-1) {
				
				document.put(getCmd, getCmdValue);
			}else{
				document.put(getCmd, getCmdValue);
			}
			
		}
		
		if (command.equals("find")) {
			document = pasreisCount(document);
			//查询find的时候是否设置有limit，如果没有，就默认返回1万条
			if (!document.containsKey("limit")) {
				//设置为默认10000条
				document.put("limit", reulstMaxsize);
			}
		}
		
		
		
		
		return document;
	}
	
	
	
	
	/**
	 *  判断find查询是否为count统计类型的
	 * @param find
	 * @return
	 */
	public Document pasreisCount(Document find) {
		
		if (find.containsKey("count")) {
			String table =find.getString("find");
			find.remove("find");
			find.put("count", table);

			Object filter = find.getString("filter");
			if ( filter!=null) {
				find.remove("filter");
				find.put("query", filter);
			}
			
			find.remove("limit");
		}
		
		return find;
	}
	 /*
     * 是否为浮点数？double或float类型。
     * @param str 传入的字符串。
     * @return 是浮点数返回true,否则返回false。
     */
    public static boolean isDoubleOrFloat(String str) {
    	if (str == null || str.equals("")) {
    		return false;
    	}
        Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");
        return pattern.matcher(str).matches();

    }


}
